package common.db;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.DriverManager;
import java.util.ArrayList;

/**
 * Created by IntelliJ IDEA.
 * User: Paskal
 * Date: Apr 6, 2009
 * Time: 6:48:25 PM
 * To change this template use File | Settings | File Templates.
 */
public class DataBasePool
{
	private static int maxConnections = 10;
	private static DataBasePool instance = null;

	private int connections = 0;
	private ArrayList<Connection> freeConnections = null;

	private DataBasePool()
	{
		freeConnections = new ArrayList<Connection>(maxConnections);
	}



	public static DataBasePool instance()
	{
		if (instance == null)
			instance = new DataBasePool();

		return instance;
	}

	public synchronized Connection getConnection(ConnectionParametar dbParam)
	{
		Connection conn = null;
		if (!freeConnections.isEmpty())
		{

			conn = freeConnections.remove(freeConnections.size() - 1);
			try
			{
				if (conn.isClosed())
				{
					conn = getConnection(dbParam);
				}
			}
			catch (SQLException e) {
				conn = getConnection(dbParam);
			}

		}
		else
		if (connections < maxConnections)
			try
			{
				Class.forName("com.mysql.jdbc.Driver").newInstance();
				conn = DriverManager
						.getConnection(dbParam.getUrl(),
								dbParam.getUserName(),
								dbParam.getPassword());
			}
			catch (Exception e)
			{
				throw new RuntimeException(e);
			}

		if (conn != null)
			connections++;

		return conn;
	}

	public synchronized Connection getConnection(ConnectionParametar dbParam, long timeout)
	{
		long startTime = System.currentTimeMillis();
		Connection conn;
		while ((conn = getConnection(dbParam)) == null)
		{
			try
			{
				wait(timeout);
			}
			catch (InterruptedException e) {}
			if (timeout > 0 && (System.currentTimeMillis() - startTime) >= timeout)
				return null;
		}
		return conn;
	}

	public synchronized void relaseConnection(Connection conn)
	{
		if (conn == null)
			connections--;
		else
			try
			{
				if (!conn.getAutoCommit())
					conn.commit();

				if ((freeConnections.size() * 2) > (connections - freeConnections.size()))
				{
					conn.close();
					connections--;
				}
				else
					freeConnections.add(conn);

			}
			catch (SQLException e)
			{
				throw new RuntimeException(e);
			}
		
		notifyAll();
	}

	public synchronized void closeAll()
	{
		for(Connection conn : freeConnections)
		{
			try
			{
				conn.close();

			}
			catch (SQLException e)
			{
				throw new RuntimeException(e);
			}
		}
		freeConnections.clear();
		connections = 0;
	}
}
